<template>
  <el-form
    ref="form"
    v-bind="$attrs"
    :model="dataForm"
    v-on="$listeners"
  >
    <slot name="header" />
    <el-row>
      <form-item :form-data="dataForm" :schema="formSchema" />
      <slot />
    </el-row>
    <div>
      <slot name="footer">
        <div v-if="showFooter" class="form-footer">
          <el-button type="primary" @click.native="handleReset">重置</el-button>
          <el-button type="primary" @click.native="handleSubmit">提交</el-button>
        </div>
      </slot>
    </div>
  </el-form>
</template>
<script>

import utils from './lib/utils'
import eventBus from './lib/event-bus'

import FormItem from './form-item'

export default {
  name: 'DebbyForm',
  components: { FormItem },
  props: {
    showFooter: {
      default: true,
      type: Boolean
    },
    /**
     * JsonSchema's format
     * {
     *     type: 'object',
     *     properties: {
     *         name: {
     *             type: 'string',
     *             ui: {
     *                 label: '姓名'
     *             }
     *         },
     *         other: {
     *             type: 'array|array-item|array-table|array-tabs',
     *             ui: '其他属性',
     *             items: {
     *                 age: {
     *                     type: 'string',
     *                     ui: {
     *                         label: '年龄'
     *                     }
     *                 },
     *                 sex: {
     *                     type: 'string',
     *                     ui: {
     *                         label: '性别'
     *                     }
     *                 }
     *             }
     *         }
     *     }
     * }
     */
    schema: {
      type: Object,
      default: () => {}
    },
    value: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      dataForm: {},
      formSchema: {}
    }
  },
  watch: {
    dataForm: {
      immediate: true,
      deep: true,
      handler: utils.debounce(function(value) {
        this.$emit('input', value)
      }, 400)
    },
    schema: {
      immediate: true,
      deep: true,
      async handler(value) {
        const _this = this
        await this.$nextTick()
        // init formData before init form ui,  because schema-type as array*,  will render by array value
        _this.dataForm = utils.parseSchema(value)
        _this.formSchema = value

        // form mounted
        _this.$emit('onFormMount', _this.dataForm)
      }
    }
  },
  async created() {
    const _this = this
    await this.$nextTick()

    /**
     * listen field-change event
     * @param idxChain {String} formData's path
     * @param value {Any} utils.get(idxChain, formData), could set by (utils.set(formData, idxChain, setValue))
     * @param schema {Object} Now components for schema
     */
    eventBus.$on('onFieldChange', (idxChain, value, schema) => {
      _this.$emit('onFieldChange', idxChain, value, _this.dataForm, schema)
    })
  },
  methods: {
    // refs[formName].setFormData(idxChain, value)
    setFormData(idxChain, value) {
      utils.set(this.dataForm, idxChain, value)
    },
    /**
     * reset form
     * then emit reset function
     */
    handleReset() {
      this.$refs.form.resetFields()
      this.$emit('reset', this.dataForm)
    },
    /**
     * submit form
     * then emit reset function by if valid === true
     */
    handleSubmit() {
      this.$refs.form.validate(valid => {
        if (valid) {
          this.$emit('submit', this.dataForm)
        }
      })
    }
  }
}
</script>

<style scoped>
.form-footer {
  display: flex;
  justify-content: flex-end;
  padding-top: 12px;
  border-top: 1px solid #f2f2f2;
}
</style>
